package main.NER.Trie;

import java.io.Serializable;
import java.util.LinkedHashSet;
import java.util.regex.Pattern;
import main.KBProcess.Element;
import main.NER.Stem;
import main.NER.Trie.CandidateExtractor.BOOTSTRAP;
import main.Ontology.ElementOntologySet;
import main.Weighting.WeightingScore;

/*
 * Author: Isaac Osesina
 */

public class NER_Candidate implements Cloneable, Serializable {
	private int candidateID;
	private String documentLanguage;
	private String documentType;
	private int documentID;
	private Element LCxt, RCxt;
	private LinkedHashSet<Integer> LCxtfragmentIDList, RCxtfragmentIDList;
	private String entityName, entityValue;
	private String preType, postType;

	private float LCxtAmbgRatio;
	private float RCxtAmbgRatio;
	private boolean LCxtAmbg;
	private boolean RCxtAmbg;

	private double depthIndex;
	private int startPos;
	private int endPos;
	private boolean deleteFlag;
	private double score;
	private boolean isCorrect;
	private int startTagPos, endTagPos;

	private Pattern entityClassRegex;
	private BOOTSTRAP bootStrap;
	private int leftContextEnd;
	private int rightContextStart;
	private String realLeft, realRight;
	private WeightingScore weightingScore;
	private int labelIndex;
	private Stem stem_LEFT, stem_RIGHT;

	public NER_Candidate() {
		deleteFlag = false;
		deleteFlag = false;
		isCorrect = false;
	}

	public NER_Candidate(int candID, Element left, Element right, int endLeft,
			int startRight, String documentLanguage, String documentType,
			String entityName, String entityValue) {
		this.candidateID = candID;
		this.LCxt = left;
		this.RCxt = right;
		this.startPos = endLeft;
		this.endPos = startRight - 1;
		this.documentLanguage = documentLanguage;
		this.documentType = documentType;
		this.entityName = entityName;
		this.entityValue = entityValue;
	}

	public void setCandidateID(int intVal) {
		candidateID = intVal;
	}

	public void setDocumentType(String strVal) {
		documentType = strVal;
	}

	public void setDocumentID(int intVal) {
		documentID = intVal;
	}

	public void setLCxtFragmentIDList(LinkedHashSet<Integer> intVal) {
		LCxtfragmentIDList = intVal;
	}

	public void setRCxtFragmentIDList(LinkedHashSet<Integer> intVal) {
		RCxtfragmentIDList = intVal;
	}

	public void setEntityName(String strVal) {
		entityName = strVal;
	}

	public void setEntityValue(String strVal) {
		entityValue = strVal;
	}

	public void setDepthIndex(double dblVal) {
		depthIndex = dblVal;
	}

	public void setStartPos(int intVal) {
		startPos = intVal;
	}

	public void setEndPos(int intVal) {
		endPos = intVal;
	}

	public void setScore(double scr) {
		score = scr;
	}

	public void setPreType(String strVal) {
		preType = strVal;
	}

	public void setPostType(String strVal) {
		postType = strVal;
	}

	public void setNewLeft(Element e) {
		LCxt = e;
	}

	public void setNewRight(Element e) {
		RCxt = e;
	}

	public void setEndTagPos(int endTagPos) {
		this.endTagPos = endTagPos;
	}

	public void setStartTagPos(int startTagPos) {
		this.startTagPos = startTagPos;
	}

	// public void setContextEval(double dblVal) {ContextSupport = dblVal;}
	// public void setContextAmbiguity(int intVal) {contextAmbiguity = intVal;}
	// public void setCxtAmbgRatio(float cxtAmbgRatio) {this.cxtAmbgRatio =
	// cxtAmbgRatio;}
	public void setLCxtAmbgRatio(float LCxtAmbgRatio) {
		this.LCxtAmbgRatio = LCxtAmbgRatio;
	}

	public void setRCxtAmbgRatio(float RCxtAmbgRatio) {
		this.RCxtAmbgRatio = RCxtAmbgRatio;
	}

	public void setLCxtAmbiguity(boolean LCxtAmbg) {
		this.LCxtAmbg = LCxtAmbg;
	}

	public void setRCxtAmbiguity(boolean RCxtAmbg) {
		this.RCxtAmbg = RCxtAmbg;
	}

	public void setEntityClassRegex(Pattern entityClassRegex) {
		this.entityClassRegex = entityClassRegex;
	}

	public void setBootStrap(BOOTSTRAP bootStrap) {
		this.bootStrap = bootStrap;
	}

	public void setLeftContextEnd(int leftContextEnd) {
		this.leftContextEnd = leftContextEnd;
	}

	public void setRightContextStart(int rightContextStart) {
		this.rightContextStart = rightContextStart;
	}

	public void setRealLeft(String realLeft) {
		this.realLeft = realLeft;
	}

	public void setRealRight(String realRight) {
		this.realRight = realRight;
	}

	public void setWeightingScore(WeightingScore weightingScore) {
		this.weightingScore = weightingScore;
	}

	public void setDocumentLanguage(String documentLanguage) {
		this.documentLanguage = documentLanguage;
	}

	public String getDocumentLanguage() {
		return documentLanguage;
	}

	public int getCandidateID() {
		return candidateID;
	}

	public String getDocumentType() {
		return documentType;
	}

	public int getDocumentID() {
		return documentID;
	}

	public LinkedHashSet<Integer> getLCxtFragmentIDList() {
		return LCxtfragmentIDList;
	}

	public LinkedHashSet<Integer> getRCxtFragmentIDList() {
		return RCxtfragmentIDList;
	}

	public String getEntityName() {
		return entityName;
	}

	public String getEntityValue() {
		return entityValue;
	}

	public double getDepthIndex() {
		return depthIndex;
	}

	public int getStartPos() {
		return startPos;
	}

	public int getEndPos() {
		return endPos;
	}

	public double getScore() {
		return score;
	}

	public String getPreType() {
		return preType;
	}

	public String getPostType() {
		return postType;
	}

	public Element getNewLeft() {
		return LCxt;
	}

	public Element getNewRight() {
		return RCxt;
	}

	public int getEndTagPos() {
		return endTagPos;
	}

	public int getStartTagPos() {
		return startTagPos;
	}

	// public double getContextEval() {return ContextSupport;}
	// public int getContextAmbiguity() {return contextAmbiguity;}
	// public float getCxtAmbgRatio() {return cxtAmbgRatio;}
	public float getLCxtAmbgRatio() {
		return LCxtAmbgRatio;
	}

	public float getRCxtAmbgRatio() {
		return RCxtAmbgRatio;
	}

	public boolean isLCxtAmbiguous() {
		return LCxtAmbg;
	}

	public boolean isRCxtAmbigous() {
		return RCxtAmbg;
	}

	public boolean isBootStrap() {
        if(bootStrap == null)
            return false;
		return bootStrap == BOOTSTRAP.YES;
	}

	public int getLeftContextEnd() {
		return leftContextEnd;
	}

	public int getRightContextStart() {
		return rightContextStart;
	}

	public String getRealRight() {
		return realRight;
	}

	public String getRealLeft() {
		return realLeft;
	}

	public Pattern getEntityClassRegex() {
		return entityClassRegex;
	}

	public WeightingScore getWeightingScore() {
		return weightingScore;
	}

	public void markAsDeleted() {
		deleteFlag = true;
	}

	public boolean isDeleted() {
		return deleteFlag;
	}

	public void markAsCorrect() {
		isCorrect = true;
	}

	public boolean isCorrect() {
		return isCorrect;
	}

	public boolean intersectsWith(NER_Candidate candidate) {
		int start = candidate.getStartPos();
		int end = candidate.getEndPos();
		if ((start <= endPos) && (end >= startPos)) {
			return true;
		} else
			return false;
	}

	public boolean isContextIntersect(NER_Candidate candidate) {
		int leftStart = this.leftContextEnd - realLeft.length();
		if (candidate.startPos < this.leftContextEnd
				&& candidate.endPos > leftStart) {
			return true;
		}
		int rightEnd = this.rightContextStart + realRight.length();
		if (candidate.startPos < rightEnd
				&& candidate.endPos > this.rightContextStart) {
			return true;
		}
		return false;
	}

	public boolean hasIdenticalValue(NER_Candidate c) {
		if (startPos == c.startPos && endPos == c.endPos)
			return true;
		else
			return false;
	}

	public int compareTo(NER_Candidate c) {
		if (candidateID == c.candidateID)
			return 0;
		if (startPos == c.startPos && endPos == c.endPos)
			return 0;
		return -1;
	}

	public int compareTo(Element e) {
		if (labelIndex == e.getLabelIndex()) {
			if (startPos == e.getIndexOf()) {
				if (this.entityValue.equalsIgnoreCase(e.getValue())) {
					return 0;
				}
			}
		}
		return -1;
	}

	public void print() {
		System.out.printf("%d|%d|%.5f|%s|%s|%d|%d|%.5f|%s|%s\n",
				getCandidateID(), getLCxtFragmentIDList(), getScore(),
				getEntityName(), getEntityValue(), getStartPos(), getEndPos(),
				getDepthIndex(), getNewLeft(), getNewRight());

	}

	@Override
	public String toString() {
		String str = String.format("%d|%s|%s|%s|%s|%.5f|%s|%s|%.5f|",
				getCandidateID(), getLCxtFragmentIDList(),
				getRCxtFragmentIDList(), getDocumentType() + "."
						+ getEntityName(), getEntityValue(), getDepthIndex(),
				getNewLeft(), getNewRight(), getScore());
		return str;
	}

	@Override
	public NER_Candidate clone() {
		try {
			return (NER_Candidate) super.clone();
		} catch (CloneNotSupportedException ex) {
			throw new InternalError();
		}
	}

	void setFragmentIDLists(LinkedHashSet<Integer> LCxtfragmentIDList,
			LinkedHashSet<Integer> RCxtfragmentIDList) {
		this.LCxtfragmentIDList = LCxtfragmentIDList;
		this.RCxtfragmentIDList = RCxtfragmentIDList;
	}

	public int getLabelIndex() {
		return labelIndex;
	}

	public void setIsCorrect(boolean isCorrect) {
		this.isCorrect = isCorrect;
	}

	public Stem getStem_LEFT() {
		return stem_LEFT;
	}

	public void setStem_LEFT(Stem stem_LEFT) {
		this.stem_LEFT = stem_LEFT;
	}

	public Stem getStem_RIGHT() {
		return stem_RIGHT;
	}

	public void setStem_RIGHT(Stem stem_RIGHT) {
		this.stem_RIGHT = stem_RIGHT;
	}
	
	public ElementOntologySet getOntologies() {
	    ElementOntologySet leftOntologies = LCxt.getOntologies();
	    ElementOntologySet rightOntologies = RCxt.getOntologies();
	    
	    return ElementOntologySet.intersection(leftOntologies, rightOntologies);
	}
}
